//--------------------------------------------------------------------------
// 
//  Copyright (c) Chili Software.  All rights reserved. 
// 
//  File: AttributeTypeMappingProvider.cs
//
//  Description: Creates the mapping for a persistent type by inspecting
//               the attributes on the type.
// 
//--------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Chili.Opf3.Relations;

namespace Chili.Opf3.Mapping.Providers
{
	/// <summary>
	/// Creates the type mapping for a persistent type by inspecting the attributes that are set
	/// on the members of the persistent type.
	/// </summary>
	public sealed class AttributeTypeMappingProvider : ITypeMappingProvider
	{
		/// <summary>
		/// Returns the persistent attribute of the type or null if the type has no 
		/// <see cref="PersistentAttribute">PersistentAttribute</see>.
		/// </summary>
		/// <param name="type">Type investigated for the <see cref="PersistentAttribute">PersistentAttribute</see>.</param>
		public PersistentAttribute GetPersistentAttribute(Type type)
		{
			if (type == null)
				throw new ArgumentNullException("type");

			// Get the persistent attributes.
			PersistentAttribute attribute = (PersistentAttribute)Attribute.GetCustomAttribute(type, typeof(PersistentAttribute), true);
			// Check if the type has a persistent attribute.
			if (attribute == null)
				return null;

			// Set the name of the type entity name if not set.
			if (attribute.Entity == null)
				attribute.Entity = type.Name;

			return attribute;
		}

		/// <summary>
		/// Returns the <see cref="FieldAttribute">FieldAttribute</see> for the given member. If the member is not mapped,
		/// null is returned.
		/// </summary>
		/// <param name="type">The persistent type that's mapping is created.</param>
		/// <param name="member">The member of the persistent type.</param>
		/// <returns>An instance of the <see cref="FieldAttribute">FieldAttribute</see> or null if the member is not mapped.</returns>
		public FieldAttribute GetMemberFieldAttribute(Type type, MemberInfo member)
		{
			if (type == null)
				throw new ArgumentNullException("type");
			if (member == null)
				throw new ArgumentNullException("member");

			return (FieldAttribute)Attribute.GetCustomAttribute(member, typeof(FieldAttribute), false);
		}

		/// <summary>
		/// Returns the <see cref="RelationAttribute">RelationAttribute</see> for the given member. If the member does not
		/// have an attribute set, null is returned.
		/// </summary>
		/// <param name="type">The persistent type that's mapping is created.</param>
		/// <param name="member">The member of the persistent type.</param>
		/// <param name="relatedType">The related object's type.</param>
		/// <returns>An instance of the <see cref="RelationAttribute">RelationAttribute</see> or null if the member does not have
		/// an attribute set.</returns>
		public RelationAttribute GetMemberRelationAttribute(Type type, MemberInfo member, Type relatedType)
		{
			if (type == null)
				throw new ArgumentNullException("type");
			if (member == null)
				throw new ArgumentNullException("member");
			if (relatedType == null)
				throw new ArgumentNullException("relatedType");

			return (RelationAttribute)Attribute.GetCustomAttribute(member, typeof(RelationAttribute), true);
		}
	}
}
